Skip to main content

Debug Param Update Issues

This guide helps you debug issues where device parameter updates are not reflecting in the GET API response, or where parameter changes made through the app are not reaching the device. Parameters (params) are the real-time values of device attributes such as power state, brightness, temperature, etc.

Before you start, have these ready:

  • Node ID of the affected device
  • The parameter name that is not updating (e.g., brightness, output)
  • Approximate time when the issue was observed

Step 1: Identify Your Symptom

SymptomGo to
Device updates params but GET API returns old/stale valuesDevice Params Not Reflecting in GET API
GET API returns error 102006 "Device reported state not found"No Param Data Found
App sends param update but device does not receive itApp Param Update Not Reaching Device
API returns error 102001 "Node is offline" when setting paramsNode Showing Offline — Cannot Set Params
Params update sometimes but are intermittently missingIntermittent Param Updates
Getting a specific error code (102xxx)Error Code Reference

Param Update Flow Overview

Understanding the flow helps identify at which stage the failure occurred.

Device → Cloud (reported params):

Step 1  Device publishes params to MQTT topic: node/<node_id>/params/local
Step 2 AWS IoT Rule "esp_set_params" routes the message to SQS queue: esp-SetDeviceShadowSQS
Step 3 Lambda esp-SetDeviceShadow reads from SQS, merges new values into existing params
Step 4 Lambda writes merged params to DynamoDB nodes_v3 table (reported_params row)
Step 5 App calls GET /user/nodes/params → Lambda esp-NodeState reads from nodes_v3 → returns params

App → Device (setting params):

Step 1  App calls PUT /user/nodes/params with new param values
Step 2 Lambda esp-NodeState checks node connectivity (online/offline) in DynamoDB
Step 3 If online → publishes to MQTT topic: node/<node_id>/params/remote
Step 4 Device receives the message and updates its state
Step 5 Device reports updated state back via node/<node_id>/params/local (Flow A above)

Device Params Not Reflecting in GET API

The most common scenario — the device is publishing param updates but the GET API still returns old values.

Step 1: Check if SetDeviceShadow Lambda is processing the updates

Go to CloudWatch → Logs Insights, select /aws/lambda/esp-SetDeviceShadow, and run:

fields @timestamp, @message
| sort @timestamp desc
| filter @message like "<node_id>"

Set the time range to cover when the param update was expected.

What to look for:

Log messageMeaningNext Step
Recent entries with no errorsLambda processed the update — check DynamoDB (Step 2)Go to Step 2
"Json is invalid"Device sent a malformed JSON payload — silently droppedFix the device firmware's JSON serialization
"Failed to update node shadow"DynamoDB write failedCheck DynamoDB table health; check Lambda IAM permissions
"ConditionalCheckFailedException"Race condition on shadow update — Lambda retries up to 3 timesIf persistent, check if multiple devices share the same node ID
No log entries at allLambda was never triggered — MQTT message did not reach SQSGo to Step 3

Step 2: Verify the param data in DynamoDB

Go to AWS Console → DynamoDB → Tables → nodes_v3.

Click Explore items and query with:

  • Partition key (node_id): the node ID
  • Sort key (node_attr_type): reported_params

What to look for:

  • Entry exists — Check the reported_params.data field (a JSON string). Confirm it contains the expected parameter values.
  • Check last_activity_timestamp — This Unix timestamp shows when the params were last updated. If it is older than expected, the device has not published recent updates.
  • No entry found — The device has never successfully published params, or the entry was never written. Continue to Step 3.
tip

If the reported_params row is missing but the device has previously reported params, check the classic AWS IoT Device Shadow for this node: IoT Core → Manage → Things → <node_id> → Device Shadow (Classic). If data exists there, it will be automatically migrated to DynamoDB on the next GET API call.

Step 3: Check if the MQTT message reached the cloud

If there are no logs in the SetDeviceShadow Lambda, the device message is not making it through the pipeline. Check each stage:

Check the IoT Rule:

  1. Go to AWS Console → IoT Core → Message routing → Rules.
  2. Find the rule named esp_set_params.
  3. Confirm the rule is Enabled (not disabled).
  4. Check the rule's SQL statement — it must be:
    select * as data, topic(2) as node_id, topic() as topic from 'node/+/params/local'
  5. Click on the rule's Error action logs to see if any messages failed to be forwarded to SQS.

Verify the device is publishing on the correct topic:

The device must publish to exactly node/<node_id>/params/local. A common mistake is publishing to a slightly different topic (e.g., wrong node ID, extra slashes, or using the /init suffix when not initializing).

Use the AWS IoT Core → MQTT test client to monitor the topic:

  1. Go to IoT Core → Test → MQTT test client.
  2. Subscribe to node/<node_id>/params/local.
  3. Trigger a param update on the device and confirm the message appears here.

If no message appears in the MQTT test client, the device is either not connected or not publishing. See Debugging Node Connection Issues.

Check the SQS queue:

  1. Go to AWS Console → SQS → esp-SetDeviceShadowSQS.
  2. Check Messages available and Messages in flight.
  3. If messages are backed up (high count in flight), the Lambda may be throttled.
  4. Check the Dead Letter Queue for failed messages: if there is a DLQ attached, click Send and receive messages → Poll for messages to inspect failures.

Step 4: Check the GET API Lambda

If the data is correct in DynamoDB but the GET API still returns stale values, check the read path.

Go to CloudWatch → Logs Insights, select /aws/lambda/esp-NodeState, and run:

fields @timestamp, @message
| sort @timestamp desc
| filter @message like "<node_id>"

Look for:

  • "Getting node state failed" (error 102005) — DynamoDB read error on the reported_params row.
  • Any errors fetching the user-node mapping — if the mapping is invalid, the API will reject the request before reading params.

No Param Data Found

Symptom: GET /user/nodes/params returns error 102006 — Device reported state not found.

This means the reported_params row in nodes_v3 is empty and no fallback data was found in the classic AWS IoT shadow either.

Step 1: Confirm the device has never reported params

Check DynamoDB nodes_v3 for the reported_params row (as described in Step 2 above). If it does not exist, the device has never successfully published to node/<node_id>/params/local.

Common reasons:

  • The device firmware has not yet called the param reporting API.
  • The device was registered recently and has not connected to the cloud yet.
  • The device published but the IoT Rule esp_set_params was disabled at the time.

Step 2: Check if the device is connected

Confirm the device is online by checking nodes_v3 for the all_attr row:

  • Partition key: the node ID
  • Sort key: all_attr

Check the connected_status field — it must be true.

If the device has never connected, it has never been able to publish params. Refer to Debugging Node Connection Issues.

Step 3: Manually trigger a param refresh

If the device is online, you can trigger a param report by publishing a request to the device. Once the device responds with its current state on node/<node_id>/params/local, the Lambda will write the data and subsequent GET API calls will succeed.


App Param Update Not Reaching Device

Symptom: App calls PUT /user/nodes/params and gets a success response, but the device does not update.

Step 1: Confirm the API call reached the Lambda

Go to CloudWatch → Logs Insights, select /aws/lambda/esp-NodeState, and run:

fields @timestamp, @message
| sort @timestamp desc
| filter @message like "<node_id>"

Look for the PUT request log entry. Confirm no errors are present.

Step 2: Verify the MQTT publish succeeded

A success response from PUT /user/nodes/params means the Lambda published the param update to the MQTT topic node/<node_id>/params/remote. It does not confirm the device received it.

Use the AWS IoT Core → MQTT test client:

  1. Subscribe to node/<node_id>/params/remote.
  2. Make the PUT API call from the app.
  3. Confirm the message appears on this topic.

If the message does not appear, check Lambda IAM permissions for IoT Core iot:Publish.

Step 3: Confirm the device is subscribed to the remote topic

The device firmware must be subscribed to node/<node_id>/params/remote to receive param updates. If the device recently reconnected, it may have lost its subscriptions.

Check the node connection logs in /aws/lambda/esp-ConnectionNode for any recent reconnection events around the time the param update was sent:

fields @timestamp, @message
| sort @timestamp desc
| filter @message like "<node_id>"

A CLIENT_INITIATED_DISCONNECT or CONNECTION_LOST just before the param update would explain why the device did not receive it.

Step 4: Check node connectivity status in DynamoDB

Go to DynamoDB → nodes_v3 and query for the all_attr row:

  • Partition key: the node ID
  • Sort key: all_attr

Check the connected_status field. If it shows true but the device is actually offline (stale status), the SET param API will publish to the MQTT topic but the device will not receive it.

The connectivity status is updated by IoT lifecycle events. If it is stale, the node connect/disconnect Lambda may have failed to update it. Check /aws/lambda/esp-ConnectionNode logs for recent events.


Node Showing Offline — Cannot Set Params

Symptom: GET /user/nodes/params (PUT) returns error 102001 — Node is offline.

The esp-NodeState Lambda checks the connected_status field in nodes_v3 before publishing to the device. If this field is false or missing, the API rejects the SET request.

Step 1: Verify the actual connectivity status

Check DynamoDB nodes_v3 all_attr row for connected_status as described above.

If connected_status is false:

  • The device is genuinely offline — fix the device's internet/Wi-Fi connection.
  • OR the status is stale (device is actually online but the field was not updated).

Step 2: Check for stale connectivity status

If the device appears online (you can ping it, or IoT Core shows it as connected) but connected_status in DynamoDB shows false:

  1. Go to CloudWatch → Logs Insights → /aws/lambda/esp-ConnectionNode.
  2. Filter by <node_id> and check the most recent event.
  3. If there is a recent CONNECT event but no corresponding DynamoDB update, the connection Lambda may have failed.

Fix: Wait for the device to reconnect — the connect event will update connected_status to true. If the status is permanently stale, check the esp-ConnectionNode Lambda for DynamoDB write errors.

Step 3: Check for device reconnect

If the device recently lost and re-established its MQTT connection, there may be a brief window where connected_status has not yet been updated to true. Wait 30–60 seconds after the device reconnects and retry the SET params call.


Intermittent Param Updates

Symptom: Params sometimes update correctly but occasionally are missed or delayed.

Check 1: SQS processing delays

High traffic or Lambda concurrency limits can cause messages to sit in the SQS queue before being processed. Check:

  1. Go to CloudWatch → esp-SetDeviceShadowSQS and look at the ApproximateAgeOfOldestMessage metric.
  2. If this value is consistently high (more than a few seconds), the Lambda is not keeping up with the message volume.

Fix: Increase the Lambda concurrency limit or check for throttling.

Check 2: DynamoDB conditional update retries

The esp-SetDeviceShadow Lambda uses a conditional write to prevent race conditions when multiple param updates arrive simultaneously. If two updates for the same node arrive within milliseconds of each other, the conditional check may fail.

The Lambda retries up to 3 times (SHADOW_UPDATE_RETRY_COUNT = 3). If all 3 retries fail, the update is silently dropped — no error is returned to SQS, so the message is not moved to a DLQ.

In CloudWatch for /aws/lambda/esp-SetDeviceShadow, search for:

fields @timestamp, @message
| filter @message like "ConditionalCheckFailedException" or @message like "<node_id>"
| sort @timestamp desc
| limit 100

If you see multiple ConditionalCheckFailedException entries for the same node, the device is publishing param updates too frequently. Consider reducing the update frequency in the device firmware.

Check 3: Malformed JSON payloads being silently dropped

If the device occasionally sends malformed JSON (e.g., during firmware updates or resets), the Lambda logs "Json is invalid" and silently drops the message without writing to DynamoDB.

In CloudWatch for /aws/lambda/esp-SetDeviceShadow, search for:

fields @timestamp, @message
| filter @message like "invalid" or @message like "Json"
| sort @timestamp desc
| limit 50

If found, check the device firmware's JSON serialization for edge cases (null values, special characters, encoding issues).

Check 4: IoT Rule error action

If the IoT Rule esp_set_params fails to route a message to SQS, the message is lost. Check the rule's Error action logs:

  1. Go to IoT Core → Message routing → Rules → esp_set_params.
  2. Check if an error action (CloudWatch Logs or SNS) is configured — if so, look for failed routing events.

Error Code Reference

Error CodeMessageLikely CauseFix
102001Node is offlineDevice is disconnected or connected_status is false in DynamoDBCheck device connectivity; wait for reconnect
102002Updating node state failedDynamoDB write failure in esp-SetDeviceShadow LambdaCheck Lambda logs; check DynamoDB table health
102003Getting node status failedCannot read connected_status from DynamoDBCheck nodes_v3 table; check Lambda IAM permissions
102004Node does not existThe node ID is not registered in nodes_v3Verify the node is registered; check nodes_v3 table
102005Getting node state failedDynamoDB read error on reported_params rowCheck Lambda logs; check DynamoDB table health
102006Device reported state not foundNo reported_params row in DynamoDB and no classic shadowDevice has never published params; check device firmware
102007Not able to find user node detailsUser-node mapping lookup failedVerify the node is mapped to this user; check user-node mapping
102008Maximum of 25 nodes can be setBatch SET params request exceeds limitSplit into smaller batches (max 25 nodes per request)

CloudWatch Log Groups Reference

Log GroupWhen to Use
/aws/lambda/esp-SetDeviceShadowPrimary log for param updates. Check here first when device params are not reflecting in the GET API
/aws/lambda/esp-NodeStateCheck GET and PUT /user/nodes/params API calls — both reading and writing params
/aws/lambda/esp-SetDeviceShadowHttpCheck when device uses the HTTPS API (PUT /node/params/local) instead of MQTT to report params
/aws/lambda/esp-LambdaSetParamsCheck automation-triggered param updates
/aws/lambda/esp-ConnectionNodeCheck node connect/disconnect events — needed when connected_status appears stale

DynamoDB Tables Reference

TableRow to CheckKeyWhat to Look For
nodes_v3reported_params rownode_id (partition), reported_params (sort)reported_params.data — the current param JSON; last_activity_timestamp — when last updated
nodes_v3all_attr rownode_id (partition), all_attr (sort)connected_status — must be true for SET params to work